"""
Python 变量完整学习笔记
=====================
本文件将详细介绍Python中变量的使用，每个知识点都配有代码示例
"""

# ==================== 1. 变量的基本概念 ====================
print("=" * 50)
print("1. 变量的基本概念")
print("=" * 50)

"""
变量就像一个容器，用来存储数据。
在Python中，变量不需要声明类型，直接赋值即可使用。
"""

# 创建一个变量，存储字符串
name = "张三"
print(f"姓名: {name}")
# 输出: 姓名: 张三

# 创建一个变量，存储数字
age = 25
print(f"年龄: {age}")
# 输出: 年龄: 25

# 创建一个变量，存储浮点数
height = 1.75
print(f"身高: {height}米")
# 输出: 身高: 1.75米

print()  # 空行分隔


# ==================== 2. 变量的命名规则 ====================
print("=" * 50)
print("2. 变量的命名规则")
print("=" * 50)

"""
变量命名规则：
1. 只能包含字母、数字和下划线
2. 不能以数字开头
3. 不能使用Python关键字
4. 区分大小写
5. 建议使用有意义的名称
"""

# ✅ 正确的命名示例
student_name = "李四"
student_age = 20
_private_var = "私有变量"
name2 = "王五"
userName = "驼峰命名法"  # 虽然可以，但Python推荐下划线命名法
user_name = "下划线命名法"  # Python推荐

print(f"学生姓名: {student_name}")
print(f"学生年龄: {student_age}")
print(f"用户名(驼峰): {userName}")
print(f"用户名(下划线): {user_name}")

# ❌ 错误的命名示例（已注释，否则会报错）
# 2name = "错误"  # 不能以数字开头
# for = "错误"  # 不能使用关键字
# user-name = "错误"  # 不能使用连字符

print()


# ==================== 3. 变量的动态类型 ====================
print("=" * 50)
print("3. 变量的动态类型")
print("=" * 50)

"""
Python是动态类型语言，同一个变量可以先后赋值为不同类型的数据
"""

# 最初是整数
x = 100
print(f"x = {x}, 类型: {type(x)}")
# 输出: x = 100, 类型: <class 'int'>

# 改为字符串
x = "现在是字符串"
print(f"x = {x}, 类型: {type(x)}")
# 输出: x = 现在是字符串, 类型: <class 'str'>

# 改为列表
x = [1, 2, 3, 4, 5]
print(f"x = {x}, 类型: {type(x)}")
# 输出: x = [1, 2, 3, 4, 5], 类型: <class 'list'>

print()


# ==================== 4. 多个变量赋值 ====================
print("=" * 50)
print("4. 多个变量赋值")
print("=" * 50)

"""
Python支持多种灵活的赋值方式
"""

# 方式1: 同时给多个变量赋相同的值
a = b = c = 10
print(f"a = {a}, b = {b}, c = {c}")
# 输出: a = 10, b = 10, c = 10

# 方式2: 同时给多个变量赋不同的值（解包赋值）
name, age, gender = "赵六", 28, "男"
print(f"姓名: {name}, 年龄: {age}, 性别: {gender}")
# 输出: 姓名: 赵六, 年龄: 28, 性别: 男

# 方式3: 从列表或元组中解包
scores = [85, 90, 78]
chinese, math, english = scores
print(f"语文: {chinese}, 数学: {math}, 英语: {english}")
# 输出: 语文: 85, 数学: 90, 英语: 78

print()


# ==================== 5. 变量的交换 ====================
print("=" * 50)
print("5. 变量的交换")
print("=" * 50)

"""
Python提供了非常简洁的变量交换方法
"""

# 传统方法（使用临时变量）
num1 = 5
num2 = 10
print(f"交换前: num1 = {num1}, num2 = {num2}")

temp = num1
num1 = num2
num2 = temp
print(f"交换后: num1 = {num1}, num2 = {num2}")

# Python的优雅方法（推荐）
x, y = 100, 200
print(f"\n交换前: x = {x}, y = {y}")

x, y = y, x  # 一行代码搞定交换
print(f"交换后: x = {x}, y = {y}")

print()


# ==================== 6. 变量的类型查看 ====================
print("=" * 50)
print("6. 变量的类型查看")
print("=" * 50)

"""
使用type()函数可以查看变量的数据类型
使用isinstance()函数可以判断变量是否为某种类型
"""

# 各种数据类型示例
integer_var = 42
float_var = 3.14
string_var = "Hello"
list_var = [1, 2, 3]
tuple_var = (1, 2, 3)
dict_var = {"name": "张三", "age": 25}
bool_var = True
none_var = None

print(f"整数: {integer_var}, 类型: {type(integer_var)}")
print(f"浮点数: {float_var}, 类型: {type(float_var)}")
print(f"字符串: {string_var}, 类型: {type(string_var)}")
print(f"列表: {list_var}, 类型: {type(list_var)}")
print(f"元组: {tuple_var}, 类型: {type(tuple_var)}")
print(f"字典: {dict_var}, 类型: {type(dict_var)}")
print(f"布尔值: {bool_var}, 类型: {type(bool_var)}")
print(f"空值: {none_var}, 类型: {type(none_var)}")

# 使用isinstance()判断类型
print(f"\n42 是整数吗? {isinstance(integer_var, int)}")
print(f"3.14 是浮点数吗? {isinstance(float_var, float)}")
print(f"'Hello' 是字符串吗? {isinstance(string_var, str)}")

print()


# ==================== 7. 类型转换 ====================
print("=" * 50)
print("7. 类型转换")
print("=" * 50)

"""
Python提供了多种类型转换函数
"""

# 字符串转整数
str_num = "123"
int_num = int(str_num)
print(f"字符串 '{str_num}' 转为整数: {int_num}, 类型: {type(int_num)}")

# 字符串转浮点数
str_float = "3.14"
float_num = float(str_float)
print(f"字符串 '{str_float}' 转为浮点数: {float_num}, 类型: {type(float_num)}")

# 数字转字符串
num = 456
str_result = str(num)
print(f"数字 {num} 转为字符串: '{str_result}', 类型: {type(str_result)}")

# 整数转浮点数
int_val = 10
float_val = float(int_val)
print(f"整数 {int_val} 转为浮点数: {float_val}")

# 浮点数转整数（会截断小数部分）
pi = 3.14159
int_pi = int(pi)
print(f"浮点数 {pi} 转为整数: {int_pi}")

# 其他类型转布尔值
print(f"\n空字符串转布尔: {bool('')}")  # False
print(f"非空字符串转布尔: {bool('hello')}")  # True
print(f"0转布尔: {bool(0)}")  # False
print(f"非0数字转布尔: {bool(42)}")  # True
print(f"空列表转布尔: {bool([])}")  # False
print(f"非空列表转布尔: {bool([1, 2])}")  # True

print()


# ==================== 8. 变量的删除 ====================
print("=" * 50)
print("8. 变量的删除")
print("=" * 50)

"""
使用del关键字可以删除变量
"""

temp_var = "临时变量"
print(f"删除前: {temp_var}")

del temp_var
print("变量已删除")

# 尝试访问已删除的变量会报错（已注释）
# print(temp_var)  # NameError: name 'temp_var' is not defined

print()


# ==================== 9. 常量的约定 ====================
print("=" * 50)
print("9. 常量的约定")
print("=" * 50)

"""
Python没有真正的常量，但约定使用全大写字母表示常量
这只是一种编程约定，提醒程序员不要修改这个值
"""

# 定义常量（约定用全大写）
PI = 3.14159
MAX_SIZE = 100
DATABASE_URL = "localhost:3306"
COMPANY_NAME = "Python学习公司"

print(f"圆周率: {PI}")
print(f"最大容量: {MAX_SIZE}")
print(f"数据库地址: {DATABASE_URL}")
print(f"公司名称: {COMPANY_NAME}")

# 虽然可以修改，但不建议这样做
# PI = 3.14  # 不推荐修改常量

print()


# ==================== 10. 变量作用域 ====================
print("=" * 50)
print("10. 变量作用域")
print("=" * 50)

"""
变量的作用域决定了变量在哪里可以被访问
"""

# 全局变量
global_var = "我是全局变量"

def demo_scope():
    # 局部变量
    local_var = "我是局部变量"
    print(f"函数内部访问全局变量: {global_var}")
    print(f"函数内部访问局部变量: {local_var}")

demo_scope()
print(f"函数外部访问全局变量: {global_var}")
# print(local_var)  # 会报错，局部变量在函数外不可访问


# 使用global关键字修改全局变量
counter = 0

def increment():
    global counter  # 声明使用全局变量
    counter += 1
    print(f"函数内: counter = {counter}")

print(f"初始值: counter = {counter}")
increment()
increment()
print(f"函数外: counter = {counter}")

print()


# ==================== 11. 变量的引用和拷贝 ====================
print("=" * 50)
print("11. 变量的引用和拷贝")
print("=" * 50)

"""
对于可变对象（如列表、字典），赋值只是创建引用
需要真正的拷贝时，要使用copy模块
"""

# 简单赋值（引用）
list1 = [1, 2, 3]
list2 = list1  # list2指向list1的同一个对象
list1.append(4)
print(f"list1: {list1}")
print(f"list2: {list2}")  # list2也改变了
# 输出: list1: [1, 2, 3, 4]
#      list2: [1, 2, 3, 4]

# 浅拷贝
import copy
list3 = [1, 2, 3]
list4 = list3.copy()  # 或者 list4 = list3[:]
list3.append(4)
print(f"\nlist3: {list3}")
print(f"list4: {list4}")  # list4不受影响
# 输出: list3: [1, 2, 3, 4]
#      list4: [1, 2, 3]

# 深拷贝（处理嵌套结构）
nested_list1 = [[1, 2], [3, 4]]
nested_list2 = copy.deepcopy(nested_list1)
nested_list1[0].append(5)
print(f"\nnested_list1: {nested_list1}")
print(f"nested_list2: {nested_list2}")  # 完全独立
# 输出: nested_list1: [[1, 2, 5], [3, 4]]
#      nested_list2: [[1, 2], [3, 4]]

print()


# ==================== 12. 变量的命名最佳实践 ====================
print("=" * 50)
print("12. 变量的命名最佳实践")
print("=" * 50)

"""
良好的变量命名可以提高代码可读性
"""

# ❌ 不好的命名
a = 18
x = "北京"
data = 85.5

# ✅ 好的命名（见名知意）
student_age = 18
city_name = "北京"
average_score = 85.5

print(f"学生年龄: {student_age}岁")
print(f"城市名称: {city_name}")
print(f"平均分: {average_score}分")

# 布尔变量建议使用is_、has_等前缀
is_student = True
has_permission = False
can_edit = True

print(f"\n是否是学生: {is_student}")
print(f"是否有权限: {has_permission}")
print(f"是否可编辑: {can_edit}")

print()


# ==================== 13. 特殊变量 ====================
print("=" * 50)
print("13. 特殊变量")
print("=" * 50)

"""
Python中有一些特殊的变量和命名约定
"""

# 单下划线开头：表示内部使用（弱私有）
_internal_var = "内部使用的变量"
print(f"内部变量: {_internal_var}")

# 双下划线开头：表示私有变量（名称改编）
__private_var = "私有变量"
print(f"私有变量: {__private_var}")

# 双下划线前后：系统定义的特殊变量
print(f"当前模块名: {__name__}")
# 当直接运行时输出: __main__

# 单下划线：临时变量或不需要的变量
for _ in range(3):
    print("循环中不需要使用索引")

print()


# ==================== 14. 变量的内存地址 ====================
print("=" * 50)
print("14. 变量的内存地址")
print("=" * 50)

"""
使用id()函数可以查看变量的内存地址
"""

var1 = 1000
var2 = 1000
var3 = var1

print(f"var1 = {var1}, 内存地址: {id(var1)}")
print(f"var2 = {var2}, 内存地址: {id(var2)}")
print(f"var3 = {var3}, 内存地址: {id(var3)}")
print(f"var1 和 var3 是同一个对象吗? {var1 is var3}")

# 小整数对象池（-5到256）
small1 = 100
small2 = 100
print(f"\nsmall1 内存地址: {id(small1)}")
print(f"small2 内存地址: {id(small2)}")
print(f"small1 和 small2 是同一个对象吗? {small1 is small2}")  # True

print()


# ==================== 15. 综合练习 ====================
print("=" * 50)
print("15. 综合练习：学生信息管理")
print("=" * 50)

"""
使用变量来管理学生信息
"""

# 学生基本信息
student_id = "2024001"
student_name = "王小明"
student_age = 20
student_gender = "男"
is_enrolled = True

# 学生成绩
score_chinese = 88
score_math = 92
score_english = 85

# 计算平均分
average = (score_chinese + score_math + score_english) / 3

# 输出学生信息卡
print("╔" + "═" * 48 + "╗")
print(f"║{' ' * 18}学生信息卡{' ' * 18}║")
print("╠" + "═" * 48 + "╣")
print(f"║ 学号: {student_id:<40} ║")
print(f"║ 姓名: {student_name:<40} ║")
print(f"║ 年龄: {student_age:<40} ║")
print(f"║ 性别: {student_gender:<40} ║")
print(f"║ 在读: {'是' if is_enrolled else '否':<40} ║")
print("╠" + "═" * 48 + "╣")
print(f"║ 语文成绩: {score_chinese:<36} ║")
print(f"║ 数学成绩: {score_math:<36} ║")
print(f"║ 英语成绩: {score_english:<36} ║")
print(f"║ 平均分: {average:<38.2f} ║")
print("╚" + "═" * 48 + "╝")

print()


# ==================== 总结 ====================
print("=" * 50)
print("总结")
print("=" * 50)

"""
变量是编程的基础，掌握以下要点：
1. 变量是存储数据的容器
2. Python是动态类型语言，变量类型可以改变
3. 变量命名要遵循规则，建议使用有意义的名称
4. 理解变量的作用域（全局/局部）
5. 注意可变对象的引用和拷贝问题
6. 使用合适的命名约定提高代码可读性
"""

print("✅ 恭喜你！已经完成Python变量的学习！")
print("💡 建议：多动手练习，加深理解！")

